package io.yizoo.system.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.google.common.cache.Cache;
import io.elm.core.CoreController;
import io.elm.core.saas.DSContext;
import io.elm.core.saas.SpringDataSourceConfig;
import io.elm.core.security.JwtUtils;
import io.yizoo.config.WorkWeixinConfig;
import io.yizoo.core.LoginWorkWeixinService;
import io.yizoo.core.message.MessageContext;
import io.yizoo.core.message.MessageFactory;
import io.yizoo.core.message.MessageService;
import io.yizoo.system.entity.*;
import io.yizoo.system.util.HttpClientUtils;
import io.yizoo.system.util.JDBCUtils;
import io.yizoo.system.util.wechat.aes.AesException;
import io.yizoo.system.util.wechat.aes.WXBizMsgCrypt;

import io.yizoo.system.util.wechat.cache.WorkWeiXinCache;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.ResultSet;
import java.util.*;

@RestController
@RequestMapping("/system/login/work/weixin/callback")
public class login_workWeixinController extends CoreController {
    @Autowired
    private WorkWeixinConfig workWechatConfig;
    @Autowired
    private Map<String,Cache<String,String>> cacheMap;
    @Autowired
    private SpringDataSourceConfig springDataSourceConfig;
    @Autowired
    private JwtUtils jwtUtils;
    @Autowired
    private io.yizoo.system.mapper.sys_menuMapper sys_menuMapper;
    @Autowired
    private TaskExecutor taskExecutor;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private LoginWorkWeixinService workWeixinService;
    @Autowired
    private MessageFactory messageFactory;
    private static final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    @Override
    protected void Init() {
        PowerEntity = sys_user.class;
        PowerUse = EnumSet.of(Power.IDDelete, Power.IDAny, Power.IDGetSingle);
    }

    private static final String SUITE_TICKET = "SuiteTicket";
    private static final String SUITE_ID = "SuiteId";
    private static final String INFO_TYPE = "InfoType";
    private static final String AUTH_CODE = "AuthCode";
    /**
     * 企业微信管理员权限
     */
    private static final String ADMIN_ROLE_ID = "1";
    /**
     * 企业微信普通用户权限
     */
    private static final String NORMAL_ROLE_ID = "2";

    @GetMapping("/data")
    public Object callBackData(@RequestParam("msg_signature") String msgSignature,
                               @RequestParam("timestamp") String timestamp,
                               @RequestParam("nonce") String nonce,
                               @RequestParam("echostr") String echostr) {
        return verifySignature(msgSignature, timestamp, nonce, echostr);
    }

    /**
     * 跳转企业微信授权页
     * @return
     */
    @PostMapping("/redirectUrl")
    public Object redirectUrl() {
        String redirectUrl = "http://www.snbg365.com/api/system/login?loginType=workWeixin&type=login&corpid=$CORPID$";
        try {
            String encode = URLEncoder.encode(redirectUrl, "UTF-8");
            String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+workWechatConfig.getSuiteId()+"&redirect_uri="+encode+"&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
            return JsonResult(new KV("url", url));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    @PostMapping("/login")
    public Object login(@RequestParam("code") String code) {
        try {
            String suiteToken = workWeixinService.getSuiteToken();
            String userTicket = getUserTicket(code,suiteToken);
            String userDetailUrl = "https://qyapi.weixin.qq.com/cgi-bin/service/auth/getuserdetail3rd?suite_access_token=" + suiteToken;
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("user_ticket", userTicket);
            String result = HttpClientUtils.doPost(userDetailUrl, paramMap);
            System.out.println("用户信息详情："+ result);


            // JDBCUtils jdbcUtils = new JDBCUtils(springDataSourceConfig);
            String key = ".free";
            DSContext.clearDataSourceType();
            DSContext.setDataSourceType("free");
            JSONObject jsonObject = JSONObject.parseObject(result);
            String thirdId = jsonObject.getString("userid");
            String corpId = jsonObject.getString("corpid");
            System.out.println("用户id："+ thirdId);
            sys_user_third sys_user_third = Ctor.HMapper.GetSingle(sys_user_third.class,
                    Ctor.DMaker().Selector
                            .From(sys_user_third.class)
                            .putFactorItem("id", thirdId)
                            .IsWhere("and third_id = #{id}",thirdId)
                            .Limit("limit 1")
                            .GetFactor());
            if (sys_user_third == null) {
                return "未查询到人员信息,请联系系统管理员";
            }

            System.out.println("人员id："+ JSON.toJSONString(sys_user_third));
            //String name = getUserName(getAccessToken(corpId), thirdId);
            sys_user user_mod = Ctor.HMapper.GetSingle(sys_user.class,
                    Ctor.DMaker().Selector
                            .From(sys_user.class)
                            .putFactorItem("id", sys_user_third.getUser_id())
                            .IsWhere("and id = #{id}")
                            .Limit("limit 1")
                            .GetFactor());
            System.out.println("人员信息："+ JSON.toJSONString(user_mod));

            System.out.println("login 4444444444444");
            if (user_mod == null) {

                return "未查询到人员信息,请联系系统管理员";
            } else {
                authenticationManager.authenticate(
                        new UsernamePasswordAuthenticationToken(sys_user_third.getThird_id()+key, sys_user_third.getThird_id())
                );
                String userName = user_mod.getUser_name();
                System.out.println("444444444444444444.5");
                final String token = jwtUtils.generateToken(userName+key);
                System.out.println("login 5555555555 token " + token);
                // userName = Ctor.GetCutUsername(userName);
                //若有人员关联，那么几个字段值用人员表记录的对应字段值
                DSContext.clearDataSourceType();
                DSContext.setDataSourceType("free");
                sys_org org_mod = Ctor.HMapper.GetSingle(sys_org.class,
                        Ctor.DMaker().Selector.From(sys_org.class, "t")
                                .putFactorItem("id", user_mod.getDept_id())
                                .Where("and t.id=#{id}").GetFactor()
                );
                System.out.println("org_mod: " + JSON.toJSONString(org_mod));

                Object roles = Ctor.CoreMapper.USelect(
                        Ctor.DMaker(JSON.toJSONString(user_mod)).Selector.From(sys_role.class, "t")
                                .Select("t.*")
                                .putFactorItem("user_id", user_mod.getId())
                                .LeftJoin(sys_role_rel_user.class, "a", "a.role_id=t.id")
                                .Where("and a.user_id=#{user_id}").GetFactor()
                );
                System.out.println("roles: " + JSON.toJSONString(roles));
                Object menu_data = sys_menuMapper.SelectUserMenuTree(
                        Ctor.DMaker().Selector.putFactorItem("user_id", user_mod.getId()).GetFactor()
                );
                System.out.println("menu_data: " + JSON.toJSONString(menu_data));
                Map<String, String> user = new HashMap<>();
                user.put("name", user_mod.getNick_name());
                user.put("id", user_mod.getId());
                user.put("corpId", corpId);
                user.put("thirdId", sys_user_third.getThird_id());
                user.put("loginType","workWeixin");
                Map<String, Object> map = JsonResult(
                        new KV("token", token),
                        new KV("success", true),
                        new KV("authpage", ""),
                        new KV("menu", menu_data),
                        new KV("user", user),
                        new KV("org",
                                new KV("name", org_mod == null ? "" : org_mod.getName())),
                        new KV("role", roles),
                        new KV("system",
                                new KV("path", "/system/main"),
                                new KV("name", "主页"))
                );
                System.out.println("work weixin login result: " + JSON.toJSONString(map));
                DSContext.clearDataSourceType();
                return map;
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            DSContext.clearDataSourceType();
        }

    }
//    private static String getUserName(String accessToken, String userId) {
//        String userStr = getUserStr(accessToken, userId);
//        String name = (String)JSONObject.parseObject(userStr).get("name");
//        return name;
//    }

    private static String getUserStr(String accessToken, String userId) {
        String getUserUrl = "https://qyapi.weixin.qq.com/cgi-bin/user/get";
        Map<String, String> userParmMap = new HashMap<>();
        userParmMap.put("access_token", accessToken);
        userParmMap.put("userid", userId);
        String userStr = HttpClientUtils.doGet(getUserUrl, userParmMap);
        return userStr;
    }

    /**
     * 地址 https://developer.work.weixin.qq.com/document/path/90236
     * {
     *     "corpid":"wpCcHpWwAAWe7TmC2xhPMqFUySjoJV4A",
     *     "title":"测试消息",
     *     "content":"content",
     *     "toTarget":"woCcHpWwAAalfd9cTcfXWET1iycDqTrQ",
     * }
     * corpid 必填 企业id
     * title 必填 标题
     * content 必填 内容
     * toTarget 必填 接收人id( thirdId)
     *
     * @param jsonStr
     * @return
     */
    @PostMapping("/sendMsg")
    public Object sendCardMessage(@RequestBody String jsonStr) {
        JSONObject param = JSONObject.parseObject(jsonStr);
        String title = param.getString("title");
        String content = param.getString("content");
        JSONArray toTarget = param.getJSONArray("toTarget");
        String sendUserId = param.getString("sendUserId");
        MessageContext context = new MessageContext(
                "free",
                toTarget.toJavaList(String.class),
                title,
                content,
                false,
                sendUserId
        );
        MessageService instance = messageFactory.getInstance(sendUserId);
        return instance.sendMsg(context);

    }

    @PostMapping("/initName")
    public Object initName(@RequestBody String jsonStr) {
        System.out.println("init 1111111111111111111111");
        DSContext.clearDataSourceType();
        DSContext.setDataSourceType("free");
        JSONObject param = JSONObject.parseObject(jsonStr);
        System.out.println("init 22" + jsonStr);
        String userId = param.getString("id");
        String name = param.getString("name");
        String nickName = param.getString("nickName");
        sys_user user_mod = Ctor.HMapper.GetSingle(sys_user.class,
                Ctor.DMaker().Selector
                        .From(sys_user.class)
                        .putFactorItem("id", userId)
                        .IsWhere("and id = #{id}")
                        .Limit("limit 1")
                        .GetFactor());
        System.out.println("init 333333333333"+JSON.toJSONString(user_mod));
        if (user_mod == null) {
            return "人员信息不存在";
        }
        user_mod.setNick_name(nickName);
        user_mod.setUser_name(name);
        System.out.println("init 444444444444"+JSON.toJSONString(user_mod));
        Ctor.HMapper.Upsert(sys_user.class, JSON.toJSONString(user_mod));
        System.out.println("init 5555555555");
        DSContext.clearDataSourceType();
        return JsonResult(new KV("code", "success"));

    }
    @PostMapping("/getAgentId")
    public Object getAgentId(@RequestParam("corpId") String corpId) {
        Cache<String, String> cache = cacheMap.get(WorkWeiXinCache.AGENT_ID_CACHE);
        if (cache == null) {
            throw new RuntimeException("缓存未初始化！");
        }
        if (cache.getIfPresent(corpId) != null) {
            return new KV("agentId", cache.getIfPresent(corpId));
        }
        Map<String, String> enterpriseConfig = workWeixinService.getEnterpriseConfig(corpId);
        String agentId = enterpriseConfig.get("agentId");
        cache.put(corpId, agentId);
        return new KV("agentId", agentId);

    }





    private String getUserTicket(String code,String suiteToken) {
        Cache<String, String> cache = cacheMap.get(WorkWeiXinCache.USER_TICKET_CACHE);
        if (cache == null) {
            throw new RuntimeException("缓存未初始化！");
        }
        if (cache.getIfPresent(code) != null) {
            return cache.getIfPresent(code);
        }

        Map<String, String> map = new HashMap<>();
        map.put("code", code);
        map.put("suite_access_token", suiteToken);
        String result = HttpClientUtils.doGet("https://qyapi.weixin.qq.com/cgi-bin/service/auth/getuserinfo3rd", map);
        System.out.println("result:" + result);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if ((int)jsonObject.get("errcode") != 0) {
            throw new RuntimeException("获取用户信息失败！ 错误信息：");
        }
        //String userId = jsonObject.getString("userid");
        String userTicket = jsonObject.getString("user_ticket");
        cache.put(code, userTicket);
        return userTicket;
    }

    private String verifySignature(String msgSignature, String timestamp, String nonce, String echostr) {
        try {
            System.out.println("msgSignature: "+ msgSignature + "timestamp :" + timestamp +"nonce: "+ nonce + "echostr" + echostr);
            WXBizMsgCrypt wxBizMsgCrypt = new WXBizMsgCrypt(workWechatConfig.getToken(), workWechatConfig.getEncodingAESKey(), workWechatConfig.getCorpId());
            System.out.println("111111111111111111111111111111");
            return wxBizMsgCrypt.VerifyURL(msgSignature, timestamp, nonce, echostr);
        } catch (AesException e) {
            throw new RuntimeException("校验失败！ 错误信息：", e);
        }
    }

    @PostMapping("/data")
    public Object callBackDataP(@RequestParam("msg_signature") String msgSignature,
                                @RequestParam("timestamp") String timestamp,
                                @RequestParam("nonce") String nonce,
                                @RequestParam(value = "corpid",required = false) String corpId,
                                @RequestBody String encryptedXml) {
        try {
            System.out.println("data接口  workWechatConfig:" + JSON.toJSONString(workWechatConfig));
            System.out.println("data 1111111111111111111111111111111");
            System.out.println("remote corpId "+ corpId);
            System.out.println("encryptedXml 1:" + encryptedXml);
            String decryptXml = null;
            try {
                System.out.println("data WXBizMsgCrypt 111111111111111");
                WXBizMsgCrypt wxBizMsgCrypt = new WXBizMsgCrypt(workWechatConfig.getToken(), workWechatConfig.getEncodingAESKey(), corpId);
                decryptXml = wxBizMsgCrypt.DecryptMsg(msgSignature, timestamp, nonce, encryptedXml);
                System.out.println("data WXBizMsgCrypt 222222222222");
            } catch (AesException e) {
                try {
                    System.out.println("data WXBizMsgCrypt 333333333333333");
                    WXBizMsgCrypt wxBizMsgCrypt = new WXBizMsgCrypt(workWechatConfig.getToken(), workWechatConfig.getEncodingAESKey(), workWechatConfig.getSuiteId());
                    decryptXml = wxBizMsgCrypt.DecryptMsg(msgSignature, timestamp, nonce, encryptedXml);
                } catch (AesException ex) {
                    System.out.println("data WXBizMsgCrypt 44444444444444444444");
                    WXBizMsgCrypt wxBizMsgCrypt = new WXBizMsgCrypt(workWechatConfig.getToken(), workWechatConfig.getEncodingAESKey(), workWechatConfig.getCorpId());
                    decryptXml = wxBizMsgCrypt.DecryptMsg(msgSignature, timestamp, nonce, encryptedXml);
                }
            }
            System.out.println("data 222222222222222222222222222");
            System.out.println("decryptXml 1:" + decryptXml);
            XmlMapper xmlMapper = new XmlMapper();
            Map map = xmlMapper.readValue(decryptXml, Map.class);
             String agentId = (String) map.get("AgentID");
            Cache<String, String> cache = cacheMap.get(WorkWeiXinCache.AGENT_ID_CACHE);
            if (cache == null) {
                throw new RuntimeException("缓存未初始化！");
            }
            if (cache.getIfPresent(corpId) != null) {
                return "success";
            }
            cache.put(corpId, agentId);
            JDBCUtils jdbcUtils = new JDBCUtils(springDataSourceConfig);
            try {
                //jdbcUtils.beginTransaction();
                jdbcUtils.executeUpdate("update work_weixi_enterprise_config set agent_id = ? where corp_id = ?", agentId, corpId);
               // jdbcUtils.commitTransaction();
            } catch (Exception e) {
              //  jdbcUtils.rollbackTransaction();
                throw new RuntimeException(e);
            }
            System.out.println("data 222222222222222222.5 :" + JSON.toJSONString(map));
        } catch (Exception e) {
           e.printStackTrace();
        }
        return "success";
    }

    @GetMapping("/command")
    public Object callBackCommand(@RequestParam("msg_signature") String msgSignature,
                                  @RequestParam("timestamp") String timestamp,
                                  @RequestParam("nonce") String nonce,
                                  @RequestParam("echostr") String echostr) {
        try {
            WXBizMsgCrypt wxBizMsgCrypt = new WXBizMsgCrypt(workWechatConfig.getToken(), workWechatConfig.getEncodingAESKey(), workWechatConfig.getCorpId());
            return wxBizMsgCrypt.VerifyURL(msgSignature, timestamp, nonce, echostr);
        } catch (AesException e) {
            throw new RuntimeException("校验失败！ 错误信息：", e);
        }
    }
    @PostMapping("/command")
    public Object callBackCommandP(@RequestParam("msg_signature") String msgSignature,
                                  @RequestParam("timestamp") String timestamp,
                                  @RequestParam("nonce") String nonce,
                                  @RequestBody String encryptedXml) {
        System.out.println("command接口 msgSignature: "+ msgSignature + "timestamp :" + timestamp +"nonce: "+ nonce + "echostr" + encryptedXml);
        try {
            System.out.println("111111111111111111111111111111");
            WXBizMsgCrypt wxBizMsgCrypt = new WXBizMsgCrypt(workWechatConfig.getToken(), workWechatConfig.getEncodingAESKey(), workWechatConfig.getCorpId());
            String decryptXml = wxBizMsgCrypt.DecryptMsg(msgSignature, timestamp, nonce, encryptedXml);
            System.out.println("222222222222222222222222222222");
            System.out.println("decryptXml:" + decryptXml);


        } catch (AesException e) {
            try {
                System.out.println("333333333333333333333333333333");
                WXBizMsgCrypt wxBizMsgCrypt = new WXBizMsgCrypt(workWechatConfig.getToken(), workWechatConfig.getEncodingAESKey(), workWechatConfig.getSuiteId());
                String decryptXml = wxBizMsgCrypt.DecryptMsg(msgSignature, timestamp, nonce, encryptedXml);
                System.out.println("decryptXml:" + decryptXml);
                if (StringUtils.isEmpty(decryptXml)) {
                    throw new RuntimeException("企业微信签名解密失败，请求体为空");
                }
                XmlMapper xmlMapper = new XmlMapper();
                Map map = xmlMapper.readValue(decryptXml, Map.class);

                    System.out.println("444444444444444444444444444444");
                    execCommand(map);

            } catch (AesException ex) {
                System.out.println("企业微信签名解密失败，错误信息："+ex.getMessage());
                return "failed";
            } catch (JsonProcessingException ex) {
                System.out.println("xml 解析失败"+ex.getMessage());
                return "failed";
            }
        }
        return "success";
    }

    private void execCommand(Map map) {
        System.out.println("execCommand");
        if (map == null) {
            throw new RuntimeException("map 为空！");
        }
        Object o = map.get(INFO_TYPE);
        if (o == null) {
            throw new RuntimeException("info_type 为空！");
        }
        String infoType = (String) o;
        switch (infoType) {
            case "suite_ticket":
                System.out.println("回调 suite_ticket");
                saveSuiteTicket(map);
                break;
            case "create_auth":
                System.out.println("回调 create_auth");
                createAuth(map);
                break;
            case "change_auth":
                changeAuth(map);
                break;
            case "cancel_auth":
                System.out.println("cancel_auth 取消应用授权");
                break;
            default:
                throw new RuntimeException("info_type 不支持！");
        }
    }

    /**
     * 更改授权
     * @param map
     */
    private void changeAuth(Map map) {
        System.out.println("change_auth 修改应用授权");
        String authCorpId = (String)map.get("AuthCorpId");
        String accessToken = workWeixinService.getAccessToken(authCorpId);
        System.out.println("accessToken: "+ accessToken);
        taskExecutor.execute(() -> {
            try {
                initMemberUser(accessToken,authCorpId);
            } catch (Exception e) {
                System.out.println("初始化授权用户错误");
                throw new RuntimeException(e);
            }
        });

    }

    /**
     * 初始化新授权用户
     * @param accessToken
     * @param authCorpId
     */
    private  void initMemberUser(String accessToken, String authCorpId) {
        System.out.println("initMemberUser");
        String url = "https://qyapi.weixin.qq.com/cgi-bin/user/list_member_auth?access_token="+ accessToken;
        Map<String, Object> param = new HashMap<>();
        param.put("cursor", null);
        param.put("limit", 50);
        String memberAuthResult = HttpClientUtils.doPost(url, param);
        System.out.println("memberAuthResult: "+ memberAuthResult);
        JSONObject jsonObject = JSON.parseObject(memberAuthResult);
        String nextCursor = jsonObject.getString("next_cursor");
        JSONArray memberAuthList = jsonObject.getJSONArray("member_auth_list");
        String convertUrl = "https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_userid?access_token="+accessToken;
        for (Object memberAuth : memberAuthList) {
            JSONObject memberAuthJson = (JSONObject) memberAuth;
            System.out.println("写入用户数据。。。");
            String openUserid = memberAuthJson.getString("open_userid");
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("openid", openUserid);
            String userId = HttpClientUtils.doPost(convertUrl, paramMap);
            DSContext.clearDataSourceType();
            DSContext.setDataSourceType("free");
            sys_user user_mod = Ctor.HMapper.GetSingle(sys_user.class,
                    Ctor.DMaker().Selector
                            .From(sys_user.class)
                            .IsWhere("and id = #{"+userId+"}",null)
                            .Limit("limit 1")
                            .GetFactor());
            if (user_mod == null) {
                initUser(authCorpId, userId, NORMAL_ROLE_ID);
            }
        }
        if (StringUtils.isNotEmpty(nextCursor)) {
            initMemberUser(accessToken, authCorpId);
        }
        DSContext.clearDataSourceType();
    }

    /**
     * 缓存临时授权码用于三方授权登录
     * @param map
     */
    private void createAuth(Map map) {
        System.out.println("create_auth 新增应用授权");
        Cache<String, String> cache = cacheMap.get(WorkWeiXinCache.AUTH_CODE_CACHE);
        if (cache == null) {
            throw new RuntimeException("缓存未初始化！");
        }
        Object o = map.get(AUTH_CODE);
        if (o == null) {
            throw new RuntimeException("auth_code 为空！");
        }
        String suiteId = (String) map.get(SUITE_ID);
        String authCode = (String) o;
        System.out.println("authCode:" + authCode);
        if (cache.getIfPresent(suiteId) == null) {
            cache.put(suiteId, authCode);
        }
        // 保存永久授权码
        createAuth(authCode);
    }

    /**
     * 缓存suiteTicket用于获取token
     * @param map
     */
    private void saveSuiteTicket(Map map) {
        Object o = map.get(SUITE_TICKET);
        if (o == null) {
            throw new RuntimeException("suite_ticket 为空！");
        }
        String suiteTicket = (String) o;
        System.out.println("suite_ticket:" + suiteTicket);
        String suiteId =(String)map.get(SUITE_ID);
        Cache<String, String> cache = cacheMap.get(WorkWeiXinCache.SUITE_TICKET_CACHE);
        if (cache == null) {
            throw new RuntimeException("缓存未初始化！");
        }

        if (cache.getIfPresent(suiteId) == null) {
            cache.put(suiteId, suiteTicket);
        }
    }

    /**
     * 获取永久授权码
     * @param authCode
     * @return
     */
    private String createAuth(String authCode) {
        System.out.println("获取永久授权码");
        String url = "https://qyapi.weixin.qq.com/cgi-bin/service/get_permanent_code?suite_access_token=";
        String suiteToken = workWeixinService.getSuiteToken();
        url += suiteToken;
        System.out.println("auth_code:" + authCode);
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("auth_code", authCode);
        String result = HttpClientUtils.doPost(url, paramMap);
        System.out.println("永久授权码结果：" + result);
        JSONObject jsonObject = JSONObject.parseObject(result);
        System.out.println("永久授权码结果：" + result);
        if (jsonObject == null) {
            throw new RuntimeException("获取永久授权码失败！");
        }

        // 写入授权的所以信息
        //PropertiesUtil.setProperty("auth_company", jsonObject.toString());

        //写入永久授权码
        String permanentCode = (String) jsonObject.get("permanent_code");
        //PropertiesUtil.setProperty("permanent_code", permanentCode);

        JSONObject jsonObject_auth_corp_info = (JSONObject) jsonObject.get("auth_corp_info");
        JSONObject authUserInfo = (JSONObject) jsonObject.get("auth_user_info");
        String corpName = (String) jsonObject_auth_corp_info.get("corp_name");
        String corpid = (String) jsonObject_auth_corp_info.get("corpid");
        String userid = authUserInfo.getString("userid");

        //写入授权企业id
        //PropertiesUtil.setProperty("auth_corpid", (String) jsonObject_auth_corp_info.get("corpid"));
        //return permanentCode;

        JDBCUtils jdbcUtils = new JDBCUtils(springDataSourceConfig);
        String sql = "INSERT INTO work_weixi_enterprise_config ("
                + "enterprise_name, corp_id, agent_id, "
                + "permanent_code, detail) VALUES ( ?, ?, ?, ?, ?)";

            //jdbcUtils.beginTransaction();
        try {
            jdbcUtils.executeUpdate(sql,corpName,corpid,"",permanentCode,result);
            System.out.println("work_weixi_enterprise_config 插入成功");
           // jdbcUtils.commitTransaction();
        } catch (Exception e) {
            System.out.println("work_weixi_enterprise_config 插入失败"+e.getMessage());
          //  jdbcUtils.rollbackTransaction();
            throw new RuntimeException(e);
        }
        System.out.println("永久授权码1：" + permanentCode);

        //String corpAccessToken = getCorpAccessToken(corpid, suiteToken, permanentCode);
        String preAuthCode = getPreAuthCode(suiteToken);
        perAuth(preAuthCode,suiteToken);
        // 初始化管理员用户
        initUser(corpid, userid, ADMIN_ROLE_ID);
        return permanentCode;
    }

    /**
     * 初始化用户信息
     * @param corpId
     * @param userId
     */
    private void initUser(String corpId,String userId,String roleId) {
        System.out.println("初始化用户信息："+ corpId+"userId: "+ userId+ "roleId: "+ roleId) ;
        DSContext.clearDataSourceType();
        DSContext.setDataSourceType("free");
        String accessToken = workWeixinService.getAccessToken(corpId);
        String userStr = getUserStr(accessToken, userId);

        if (userStr == null) {
            return ;
        }
        System.out.println("userStr:" + userStr);
        JSONObject jsonObject = JSONObject.parseObject(userStr);
        if (jsonObject == null) {
            return ;
        }
        sys_user sysUser = new sys_user();
        sysUser.setId(UUID.randomUUID().toString());
        sysUser.setAvatar(jsonObject.getString("avatar"));
        sysUser.setDept_id("1");
        sysUser.setUser_name(userId);
        sysUser.setNick_name("default");
        sysUser.setPassword(passwordEncoder.encode(userId));
        sysUser.setEmail(jsonObject.getString("email"));
        sysUser.setSex("1".equals(jsonObject.getString("gender")) ? "男" : "女");
        sysUser.setPhonenumber(jsonObject.getString("telephone"));
        Ctor.HMapper.Upsert(sys_user.class,JSON.toJSONString(sysUser));
        System.out.println(userId + " 写入完成1");
        sys_user_third sysUserThird = new sys_user_third();
        sysUserThird.setUser_id(sysUser.getId());
        sysUserThird.setId(UUID.randomUUID().toString());
        sysUserThird.setCorp_id(corpId);
        sysUserThird.setThird_id(userId);
        sysUserThird.setThird_type("workWeixin");
        sysUserThird.setUser_open_id(jsonObject.getString("open_userid"));
        Ctor.HMapper.Upsert(sys_user_third.class,JSON.toJSONString(sysUserThird));
        System.out.println(userId + " 写入完成2");
        sys_role_rel_user SysRoleRelUser = new sys_role_rel_user();
        SysRoleRelUser.setId(UUID.randomUUID().toString());
        SysRoleRelUser.setRole_id(roleId);
        SysRoleRelUser.setUser_id(userId);
        Ctor.HMapper.Upsert(sys_role_rel_user.class,JSON.toJSONString(SysRoleRelUser));
        System.out.println(userId + " 写入完成3");
    }


    private void perAuth(String preAuthCode,String suitToken) {
        System.out.println("实际开始认证");
        String url = "https://qyapi.weixin.qq.com/cgi-bin/service/set_session_info?suite_access_token=";
        url += suitToken;
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("pre_auth_code", preAuthCode);
        paramMap.put("auth_type", workWechatConfig.getAuthType());
        paramMap.put("session_info",new JSONObject());
        String result = HttpClientUtils.doPost(url, paramMap);
        System.out.println("set_session_info:" + result);
        JSONObject jsonObject = JSONObject.parseObject(result);
        System.out.println("set_session_info:" + result);
        if (jsonObject.get("errcode") != null && jsonObject.get("errcode").equals(0)) {
            System.out.println("认证成功");
        } else {
            System.out.println("认证失败");
        }

    }

    private String getPreAuthCode(String suiteToken) {
        System.out.println("获取pre_auth_code");
        String url = "https://qyapi.weixin.qq.com/cgi-bin/service/get_pre_auth_code?suite_access_token=";
        url += suiteToken;
        JSONObject jsonObj = JSONObject.parseObject(HttpClientUtils.doGet(url,new HashMap<>()));
        String preAuthCode = (String) jsonObj.get("pre_auth_code");
        System.out.println("pre_auth_code结果:" + jsonObj.toJSONString());
        return preAuthCode;


    }



    /**
     * 获取企业accessToken
     * @param authCorpId
     * @param suiteToken
     * @param permanentCode
     * @return
     */
    private String getCorpAccessToken(String authCorpId,String suiteToken,String permanentCode) {
        Cache<String, String> cache = cacheMap.get(WorkWeiXinCache.CORP_ACCESS_TOKEN_CACHE);
        if (cache == null) {
            throw new RuntimeException("缓存未初始化！");
        }
        if (cache.getIfPresent(authCorpId) == null) {
            String accessToken = getCorpAccessToken(authCorpId, suiteToken, permanentCode);
            cache.put(authCorpId, accessToken);
        }
        String url = "https://qyapi.weixin.qq.com/cgi-bin/service/get_corp_token?suite_access_token=";
        url += suiteToken;
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("auth_corpid", authCorpId);
        paramMap.put("permanent_code", permanentCode);
        String result = HttpClientUtils.doPost(url, paramMap);
        JSONObject jsonObject = JSONObject.parseObject(result);
        String accessToken = (String) jsonObject.get("access_token");
        if (StringUtils.isEmpty(accessToken)) {
            throw new RuntimeException("获取accessToken失败！");
        }
        cache.put(authCorpId, accessToken);
        return accessToken;
    }









    public static void main(String[] args) {
        System.out.println(passwordEncoder.encode("woCcHpWwAAalfd9cTcfXWET1iycDqTrQ"));
//        String xml = "<xml>\n" +
//                "<SuiteId><![CDATA[ww4asffe99e54c0fxxxx]]></SuiteId>\n" +
//                "<InfoType> <![CDATA[suite_ticket]]></InfoType>\n" +
//                "<TimeStamp>1403610513</TimeStamp>\n" +
//                "<SuiteTicket><![CDATA[asdfasfdasdfasdf]]></SuiteTicket>\n" +
//                "</xml>";
//
//
//        try {
//            Map map = XmlMapper.builder().build().readValue(xml, Map.class);
//            System.out.println(JSON.toJSONString(map));
//        } catch (JsonProcessingException e) {
//            throw new RuntimeException(e);
//        }
        String redirectUrl = "http://www.snbg365.com/v/system/login?loginType=workWeixin&&corpid=$CORPID$";
            String encode = null;
            try {
                encode = URLEncoder.encode(redirectUrl, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
            String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww45eb3068dd994505&redirect_uri="+encode+"&response_type=code&scope=snsapi_userinfo&agentid=1000003&state=STATE#wechat_redirect";
            System.out.println(url);
    }
}
